package com.jidong.test_springboot.web;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.activiti.engine.RepositoryService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jidong.test_springboot.dao.RoleDao;
import com.jidong.test_springboot.dao.UserDao;
import com.jidong.test_springboot.dao.UserRoleDao;
import com.jidong.test_springboot.entity.Dept;
import com.jidong.test_springboot.entity.Role;
import com.jidong.test_springboot.entity.User;
import com.jidong.test_springboot.entity.UserRole;
import com.jidong.test_springboot.entity.UserWithDept;
import com.jidong.test_springboot.module.LoginUser;
import com.jidong.test_springboot.module.UserModule;
import com.jidong.test_springboot.service.DeptService;
import com.jidong.test_springboot.service.UserService;
import com.jidong.test_springboot.shiro.JwtToken;
import com.jidong.test_springboot.util.JWTUtil;
import com.jidong.test_springboot.vo.ResultData;

import lombok.extern.slf4j.Slf4j;
@RestController
@Slf4j
@RequestMapping("user/")
public class UserServlet{

	@Autowired
	private UserDao dao;
	@Autowired
	private UserRoleDao userRoleDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private DeptService deptService;
	
	@Autowired
	private UserService userService;
	
	
	/*  修改后端代码，为了保持原来的代码，我们复制一下 ，重命名为login2 参数是LoginUser实体类，再添加
	 * @RequestBody 注解，是指将前端发来的json数据转为了LoginUser类型的实体。
	 * LoginUser是自己定义的。我们新建一个module包，把LoginUser创建，
	 * **/
	@RequestMapping(value="login.do",method=RequestMethod.POST)  // 只接受post请求方式
	@ResponseBody
	public ResultData login(@RequestBody LoginUser user) {
		String username=user.getUsername();
		String password=user.getPassword();
		// 以前的代码是调用了shiro的登录判断，默认去realm验证token了，但是realm没有验证用户名和密码的有效性，
		// (因为每个请求都走这个方法，不必都读库 只验证token就行了)
		// 所以登录这里直接读库，不走realm
		//读库
		User u=userService.selectUserByUnamePwd(username,password);
		if(u!=null) {
			//创建一个token
			//用工具类 根据用户名和密码生成一个jwt的token
			String token=JWTUtil.sign(username, password);
			
			ResultData result=new ResultData();
			result.setCode(200);
			result.setMsg("登录成功");
			result.setResult("{\"token\":\""+token+"\"}");//把token给前端，前端下次登录的携带该token
			return result;
		}else {
			ResultData result=new ResultData();
			result.setCode(401);
			result.setMsg("登录失败");
			return result;
		}
	}
	

	@RequestMapping(value="login_old.do")
	@ResponseBody
	public ResultData login_old(String username,String password) {
		//创建话题
		Subject sub=SecurityUtils.getSubject();
		//创建一个token
		//UsernamePasswordToken token=new UsernamePasswordToken(username,password);
		
		//用工具类 根据用户名和密码生成一个jwt的token
		String token=JWTUtil.sign(username, password);
		
		//AuthenticationToken 类型是login需要的
		sub.login(new JwtToken(token));//如果登录失败就会抛出异常，如果登录成功就会往下执行代码
		
		
		ResultData result=new ResultData();
		result.setCode(200);
		result.setMsg("登录成功");
		result.setResult("{token:"+token+"}");//把token给前端，前端下次登录的携带该token
		return result;
	}
	

	@RequestMapping("regist.do")
	public ResultData regist(String username,String password,String gender,int age)  {
		User u = new User(username, gender, age,password);
		int result = dao.insert(u);

		if (result > 0) {
			return new ResultData().setCode(200).setMsg("注册成功");
		} else {
			return new ResultData().setCode(200).setMsg("注册失败");
		}
	}
	
	/**用户管理里的添加用户操作**/
	@RequestMapping("add.do")
	public ResultData add(User u,String roleId)  {
		int result = dao.insert(u);
		System.out.println(u.getId()+"是否能获得到新插入的数据的id呢？");
		
		String[] strIds=roleId.split(",");
		for(String tmp:strIds) {
			int rid=Integer.parseInt(tmp);//拿到一个roleid
			//拿到用户id
			//拼成一个UserRole对象
			UserRole ur=new UserRole(u.getId(),rid);
			//将UserRole交给userRoleDao
			userRoleDao.insert(ur);
		}
		
		if (result > 0) {
			return new ResultData().setCode(200).setMsg("添加成功");
		} else {
			return new ResultData().setCode(200).setMsg("添加失败");
		}
	}
	
	/**头像上传请求,用于用户管理中的添加的时候的文件上传***/
	@PostMapping(value="uploadAvatar")
	@ResponseBody
	public ResultData upload(HttpServletRequest request,HttpServletResponse response) {
		ResultData result=new ResultData();
		try {
			String ctxPath="E:";
			String bizPath="files";
			String nowDay=new SimpleDateFormat("yyyyMMdd").format(new Date());
			//把图片保存在这个文件夹里
			File avatarPath=new File(ctxPath+File.separator+bizPath+File.separator+nowDay);
			if(!avatarPath.exists()) {
				avatarPath.mkdirs();
			}
			//获取前端的文件
			MultipartHttpServletRequest mrequest=(MultipartHttpServletRequest)request;
			MultipartFile mf=mrequest.getFile("file");//前端传来的文件
			String oldName=mf.getOriginalFilename();
			String newName=oldName.substring(0,oldName.lastIndexOf("."))+
					System.currentTimeMillis()+
					oldName.substring(oldName.lastIndexOf("."));
			String saveName=avatarPath+File.separator+newName;
			File avatar=new File(saveName);
			FileCopyUtils.copy(mf.getBytes(), avatar);
			//把头像的完整路径减去E盘目录，发给前端
			String dbPath=bizPath+File.separator+nowDay+File.separator+newName;
			result.setMsg("ok");
			result.setResult(dbPath);//把名字给前端
			return result;
		} catch (IOException e) {
			e.printStackTrace();
			return result.setCode(407).setMsg("fail");
		}
	}
	
	
	/**
	 * 预览图片
	 * 请求地址：http://localhost:8088/user/getAvatarView/{files/20190119/logo.jpg}
	 * 
	 * @param request
	 * @param response
	 */
	@GetMapping(value = "/getAvatarView/**")
	public void view(HttpServletRequest request, HttpServletResponse response) {
		// ISO-8859-1 ==> UTF-8 进行编码转换
		String imgPath = extractPathFromPattern(request);
		// 其余处理略
		InputStream inputStream = null;
		OutputStream outputStream = null;
		try {
			imgPath = imgPath.replace("..", "");
			if (imgPath.endsWith(",")) {
				imgPath = imgPath.substring(0, imgPath.length() - 1);
			}
			response.setContentType("image/jpeg;charset=utf-8");
			String localPath = "E:";
			String imgurl = localPath + File.separator + imgPath;
			inputStream = new BufferedInputStream(new FileInputStream(imgurl));
			outputStream = response.getOutputStream();
			byte[] buf = new byte[1024];
			int len;
			while ((len = inputStream.read(buf)) > 0) {
				outputStream.write(buf, 0, len);
			}
			response.flushBuffer();
		} catch (IOException e) {
			log.error("预览图片失败" + e.getMessage());
			// e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
		}

	}
	
	
	/**
	  *  把指定URL后的字符串全部截断当成参数 
	  *  这么做是为了防止URL中包含中文或者特殊字符（/等）时，匹配不了的问题
	 * @param request
	 * @return
	 */
	private static String extractPathFromPattern(final HttpServletRequest request) {
		String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
		String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
		return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
	}

	
	// @RequiresRoles({"guanliyuan"})
	@RequestMapping("list.do")
	@ResponseBody
	public ResultData list(UserModule module)  {
		IPage<UserWithDept> page=new Page(module.getCurrent(),module.getPageSize());
		QueryWrapper<UserWithDept> query=new QueryWrapper<>();
		if(module.getName()!=null) {
			query.like("uname", module.getName());
		}
		IPage<UserWithDept> pages = dao.selectUserList(page,query); //数据
		List<UserWithDept> users=pages.getRecords();
		int current=module.getCurrent();//将当前页码取出来，还发给前端
		int total=(int)pages.getTotal(); // 将总条数读出来，发给前端
		JSONObject record=new JSONObject();
		record.put("data", users);
		record.put("current", current);
		record.put("total", total);// 总数据 并非当前读了多少数据
		
		
		return new ResultData().setCode(200).setResult(record);//把json交给前端
	}
	
	/*用户列表中的部门信息加载
	 * [
	 * {title:
	 * value:
	 * key:
	 * children[]
	 * },
	 * ]
	 * 
	 * 
	 * **/
	@RequestMapping("listDeptTree.do")
	@ResponseBody
	public ResultData listDeptTree()  {
		
		List<Dept> depts=deptService.selectAll();
		JSONArray j_depts=new JSONArray();
		this.getDeptTree(j_depts,depts,null);
		
		System.out.println(j_depts);
		
		ResultData data=new ResultData();
		data.setCode(200).setMsg("");
		return data.setResult(j_depts);
		
	}
	
	
	
	
	
	
	private void getDeptTree(JSONArray j_depts, List<Dept> depts,Dept parent) {
		for(Dept d:depts) {
			JSONObject j_d=getDetp2Json(d);
			if(parent==null) {
				if("1".equals(d.getIsParent())) {
					JSONArray children=new JSONArray();
					j_d.put("children", children);
					getDeptTree(children,depts,d);
				}
				
				if(d.getParentId()==0) {
					j_depts.add(j_d);
				}
			}else {
				if(parent.getId()==d.getParentId() ) {
					j_depts.add(j_d);
					if("1".equals(d.getIsParent())) {
						JSONArray children=new JSONArray();
						j_d.put("children", children);
						getDeptTree(children,depts,d);
					}
				}
			}
		}
	}


	private JSONObject getDetp2Json(Dept d) {
		JSONObject ob=new JSONObject();
		ob.put("title", d.getDeptName());
		ob.put("key", d.getId()+"");
		ob.put("value", d.getId()+"");
		return ob;
	}


	@RequestMapping("update.do")
	//@RequiresRoles({"guanliyuan"})
	public ResultData update(User u) throws IOException, ServletException {
		int r=dao.updateById(u);
		if(r>0) {
			return new ResultData().setCode(200).setMsg("更新成功");
		}else {
			return new ResultData().setCode(200).setMsg("更新失败");
		}
	}

	@RequestMapping("delete.do")
	//@RequiresRoles({"guanliyuan"})
	public ResultData delete(int id) throws IOException, ServletException {
		int r=dao.deleteById(id);
		if(r>0) {
			return new ResultData().setCode(200).setMsg("ok");
		}else {
			return new ResultData().setCode(200).setMsg("fail");
		}

	}
	
	// 1001,1002,1003,1004,1006,1007,1008,1009,1010,1011,
	@RequestMapping("batchdel.do")
	//@RequiresRoles({"guanliyuan"})
	public ResultData batchdel(String ids)  {
		try {
			String[] strs=ids.split(",");
			List<Integer> list=new ArrayList();
			for(String s:strs) {
				int id=Integer.parseInt(s);
				list.add(id);
			}
			dao.deleteBatchIds(list);
			// 删除用户角色关联表里的该用户所属的角色关联
			QueryWrapper<UserRole> query=new QueryWrapper<>();
			query.in("user_id", list);
			userRoleDao.delete(query);
			return new ResultData().setCode(200).setMsg("删除成功").setResult(null);
		} catch (Exception e) {
			e.printStackTrace();
			return new ResultData().setCode(200).setMsg("删除失败");
		}
	}
	
	/**这个方法用于编辑用户的时候提前加载用户的所有信息，返回的是一个user*/
	@RequestMapping("getUserById")
	public ResultData getUserById(int id) {
		User u=dao.selectById(id);
		return new ResultData().setCode(200).setResult(u);
	}
	
	/**用于用户管理中显示所有角色的方法，便于前端选中哪个角色进行授权*/
	@RequestMapping("listAllRoleTree.do")
	public ResultData getAllRoleList() {
		JSONArray result=new JSONArray();
		List<Role> list=roleDao.selectList(null);
		for(Role r:list) {
			JSONObject o=new JSONObject();
			o.put("key", r.getId()+"");
			o.put("value", r.getId()+"");
			o.put("title", r.getName());
			result.add(o);
		}
		return new ResultData().setCode(200).setResult(result);
	}

}
